κ²¬κ³ ν μλ°μ€ν¬λ¦½νΈ API μ ν¨μ± κ²μ¬ νλ μμν¬λ‘ μΉ νλ«νΌ νμ€ μ€μλ₯Ό 보μ₯νμΈμ. μ½λ νμ§, μ μ§λ³΄μμ±, μνΈμ΄μ©μ±μ κ°μ νκΈ° μν μ ν¨μ± κ²μ¬ νλ μμν¬ κ΅¬μΆ λ° νμ© λ°©λ²μ μμλ΄ λλ€.
μΉ νλ«νΌ νμ€ μ€μ: μλ°μ€ν¬λ¦½νΈ API μ ν¨μ± κ²μ¬ νλ μμν¬
λμμμ΄ μ§ννλ μΉ κ°λ° νκ²½μμ μΉ νλ«νΌ νμ€μ μ€μνλ κ²μ κ²¬κ³ νκ³ μ μ§λ³΄μκ° μ©μ΄νλ©° μνΈμ΄μ© κ°λ₯ν μ ν리μΌμ΄μ μ ꡬμΆνλ λ° λ§€μ° μ€μν©λλ€. μλ μμ΄λ μΉ μ»¨μμμ(W3C)μ΄λ WHATWGμ κ°μ κΈ°κ΄μμ μ μνλ μ΄λ¬ν νμ€μ μΉμ¬μ΄νΈμ μ ν리μΌμ΄μ μ΄ λ€μν λΈλΌμ°μ μ κΈ°κΈ°μμ μΌκ΄λκ² μλνλλ‘ λ³΄μ₯ν©λλ€. μ΄λ¬ν μ€μλ₯Ό λ¬μ±νλ ν΅μ¬ μμλ μ ν리μΌμ΄μ λ΄μμ μ¬μ©λλ μλ°μ€ν¬λ¦½νΈ APIλ₯Ό κ²μ¦νλ κ²μ λλ€. μ΄ κΈμμλ μλ°μ€ν¬λ¦½νΈ API μ ν¨μ± κ²μ¬ νλ μμν¬μ κ°λ κ³Ό μ΄μ , κ·Έλ¦¬κ³ μ΄λ₯Ό ν¨κ³Όμ μΌλ‘ ꡬμΆνκ³ νμ©νλ λ°©λ²μ μ΄ν΄λ΄ λλ€.
μΉ νλ«νΌ νμ€ μ€μμ μ€μμ±
μΉ νλ«νΌ νμ€μ κ°λ°μ, λΈλΌμ°μ λ° κΈ°ν μΉ κΈ°μ μ μν 곡ν΅μ κΈ°λ°μ μ 곡ν©λλ€. μ΄λ¬ν νμ€μ μ€μνλ©΄ λ€μκ³Ό κ°μ μ¬λ¬ μ΄μ μ΄ μμ΅λλ€:
- μνΈμ΄μ©μ±: μ ν리μΌμ΄μ μ΄ λ€μν λΈλΌμ°μ μ κΈ°κΈ°μμ μΌκ΄λκ² μλνμ¬ ν΅μΌλ μ¬μ©μ κ²½νμ μ 곡ν©λλ€.
- μ μ§λ³΄μμ±: νμ€νλ μ½λλ μκ°μ΄ μ§λλ μ΄ν΄, μ μ§λ³΄μ, μ λ°μ΄νΈκ° λ μ½μ΅λλ€.
- μ±λ₯: νμ€μ μ€μνλ μ½λλ μ’ μ’ λΈλΌμ°μ 곡κΈμ 체μ μν΄ μ±λ₯μ΄ μ΅μ νλ©λλ€.
- μ κ·Όμ±: λ§μ μΉ νμ€μ μ κ·Όμ±μ μ¦μ§νμ¬ μ₯μ κ° μλ μ¬λλ€λ μ ν리μΌμ΄μ μ μ¬μ©ν μ μλλ‘ λ³΄μ₯ν©λλ€.
- 보μ: νμ€μλ μ’ μ’ λ³΄μ λͺ¨λ² μ¬λ‘κ° ν¬ν¨λμ΄ μμ΄ μ·¨μ½μ±μ μνμ μ€μ λλ€.
- λ―Έλ λμμ±: νμ€μ μ€μνλ©΄ λΈλΌμ°μ κΈ°μ μ λ³νμ λλΉνμ¬ μ ν리μΌμ΄μ μ λ―Έλλ₯Ό 보μ₯νλ λ° λμμ΄ λ©λλ€.
μΉ νλ«νΌ νμ€μ μ€μνμ§ μμΌλ©΄ λ€μκ³Ό κ°μ λ¬Έμ κ° λ°μν μ μμ΅λλ€:
- λΈλΌμ°μ λΉνΈνμ±: νΉμ λΈλΌμ°μ μμ μ ν리μΌμ΄μ μ΄ μ¬λ°λ₯΄κ² μλνμ§ μκ±°λ μ ν μλνμ§ μμ μ μμ΅λλ€.
- 보μ μ·¨μ½μ : λΉνμ€ μ½λλ 보μ νμ μ μ λ°ν μ μμ΅λλ€.
- μ±λ₯ μ ν: λΉνμ€ μ½λλ ν¨μ¨μ±μ΄ λ¨μ΄μ Έ μ±λ₯ λ¬Έμ λ₯Ό μΌμΌν¬ μ μμ΅λλ€.
- μ μ§λ³΄μ λΉμ© μ¦κ°: λΉνμ€ μ½λλ₯Ό μμ νλ κ²μ μκ°κ³Ό λΉμ©μ΄ λ§μ΄ λ€ μ μμ΅λλ€.
μλ°μ€ν¬λ¦½νΈ API μ ν¨μ± κ²μ¬ νλ μμν¬λ 무μμΈκ°?
μλ°μ€ν¬λ¦½νΈ API μ ν¨μ± κ²μ¬ νλ μμν¬λ μ ν리μΌμ΄μ μμ μ¬μ©λλ μλ°μ€ν¬λ¦½νΈ APIκ° μΉ νλ«νΌ νμ€μ μ€μνλμ§ μλμΌλ‘ νμΈνλ λ° μ¬μ©λλ λꡬ λ° κΈ°μ μ μ§ν©μ λλ€. μΌλ°μ μΌλ‘ λ€μμ ν¬ν¨ν©λλ€:
- μμ API λμ μ μ: APIμ μμ λ°μ΄ν° μ ν, κ° λ° κΈ°λ₯μ λͺ μνλ κ²μ ν¬ν¨ν©λλ€.
- μ ν¨μ± κ²μ¬ κ·μΉ μμ±: μ΄ κ·μΉλ€μ APIκ° κ·μ μ μ€μνλ κ²μΌλ‘ κ°μ£ΌλκΈ° μν΄ μΆ©μ‘±ν΄μΌ ν κΈ°μ€μ μ μν©λλ€.
- μ ν¨μ± κ²μ¬ νλ‘μΈμ€ μλν: ν μ€νΈ νλ μμν¬μ λꡬλ₯Ό μ¬μ©νμ¬ μ ν¨μ± κ²μ¬ κ·μΉμ μλμΌλ‘ μ€ννκ³ μλ° μ¬νμ λ³΄κ³ νλ κ²μ ν¬ν¨ν©λλ€.
μλ°μ€ν¬λ¦½νΈ API μ ν¨μ± κ²μ¬ νλ μμν¬ μ¬μ©μ μ΄μ
μλ°μ€ν¬λ¦½νΈ API μ ν¨μ± κ²μ¬ νλ μμν¬λ₯Ό ꡬννλ©΄ λ€μκ³Ό κ°μ μλ§μ μ΄μ μ΄ μμ΅λλ€:
- μ€λ₯μ μ‘°κΈ° λ°κ²¬: μ ν¨μ± κ²μ¬λ κ°λ° νλ‘μΈμ€ μ΄κΈ°μ μ€λ₯λ₯Ό κ°μ§νμ¬ νλ‘λμ μΌλ‘ μ νλλ κ²μ λ°©μ§ν©λλ€.
- μ½λ νμ§ ν₯μ: νμ€μ κ°μ ν¨μΌλ‘μ¨ μ ν¨μ± κ²μ¬λ λ κΉ¨λνκ³ μΌκ΄μ± μμΌλ©° μ μ§λ³΄μνκΈ° μ’μ μ½λλ₯Ό μ΄μ§ν©λλ€.
- λλ²κΉ μκ° λ¨μΆ: μ ν¨μ± κ²μ¬ νλ μμν¬μ λͺ νν μ€λ₯ λ©μμ§λ λ¬Έμ μ μμΈμ μ νν μ°Ύμλ΄μ΄ λλ²κΉ μκ°μ μ€μ¬μ€λλ€.
- μνΈμ΄μ©μ± κ°ν: μ ν¨μ± κ²μ¬λ APIκ° λ€μν λΈλΌμ°μ μ κΈ°κΈ°μμ μ¬λ°λ₯΄κ² μλνλλ‘ λ³΄μ₯ν©λλ€.
- μ λ’°λ μ¦κ°: APIκ° κ²μ¦λμλ€λ μ¬μ€μ μ ν리μΌμ΄μ μ νμ§κ³Ό μ λ’°μ±μ λν νμ μ μ€λλ€.
- μλνλ ν μ€νΈ: μλνλ ν μ€νΈ λꡬμμ ν΅ν©μ μ ν리μΌμ΄μ μ΄ λ°μ ν¨μ λ°λΌ μ§μμ μΈ μ ν¨μ± κ²μ¬λ₯Ό 보μ₯ν©λλ€.
- λ¬Έμν: μ ν¨μ± κ²μ¬ κ·μΉμ APIμ μμ λμμ λν λ¬Έμ μν μ ν μ μμ΅λλ€.
μλ°μ€ν¬λ¦½νΈ API μ ν¨μ± κ²μ¬ νλ μμν¬ κ΅¬μΆνκΈ°
μλ°μ€ν¬λ¦½νΈ API μ ν¨μ± κ²μ¬ νλ μμν¬λ₯Ό ꡬμΆνλ λ°μλ κ°λ¨ν μλ νμΈλΆν° μ κ΅ν μλν ν μ€νΈ μμ€ν μ μ΄λ₯΄κΈ°κΉμ§ μ¬λ¬ μ κ·Ό λ°©μμ΄ μμ΅λλ€. λ€μμ κΈ°λ³Έ νλ μμν¬λ₯Ό ꡬμΆνκΈ° μν λ¨κ³λ³ κ°μ΄λμ λλ€:
1. API λͺ μΈ μ μνκΈ°
첫 λ²μ§Έ λ¨κ³λ μ ν¨μ±μ κ²μ¬νλ €λ APIμ λͺ μΈλ₯Ό λͺ ννκ² μ μνλ κ²μ λλ€. μ¬κΈ°μλ λ€μμ λ¬Έμννλ κ²μ΄ ν¬ν¨λ©λλ€:
- API μλν¬μΈνΈ: APIμ URLμ λλ€.
- μμ² λ©μλ: κ° APIμ μ¬μ©λλ HTTP λ©μλ(GET, POST, PUT, DELETE λ±)μ λλ€.
- μμ² λ§€κ°λ³μ: λ°μ΄ν° μ ν, μ ν¨μ± κ²μ¬ κ·μΉ, νμ νλλ₯Ό ν¬ν¨νμ¬ μμ²μ 보λ΄μΌ νλ λ°μ΄ν°μ λλ€.
- μλ΅ νμ: λ°μ΄ν° μ ν, μ ν¨μ± κ²μ¬ κ·μΉ, μμ κ°μ ν¬ν¨νμ¬ APIκ° λ°ννλ λ°μ΄ν°μ ꡬ쑰μ λλ€.
- μ€λ₯ μ½λ: APIκ° λ°νν μ μλ κ°λ₯ν μ€λ₯ μ½λμ κ·Έ μλ―Έμ λλ€.
APIλ₯Ό λ¬ΈμννκΈ° μν΄ OpenAPI(μ΄μ Swagger)λ RAMLκ³Ό κ°μ 곡μ API λͺ μΈ νμμ μ¬μ©νλ κ²μ κ³ λ €ν΄ λ³΄μΈμ. μ΄λ¬ν νμμ APIλ₯Ό μ€λͺ νλ νμ€νλ λ°©λ²μ μ 곡νλ©° λ¬Έμ, μ½λ μ€ν , μ ν¨μ± κ²μ¬ κ·μΉμ μμ±νλ λ° μ¬μ©λ μ μμ΅λλ€.
μμ (OpenAPI):
openapi: 3.0.0
info:
title: My API
version: 1.0.0
paths:
/users:
get:
summary: Get a list of users
responses:
'200':
description: μ¬μ©μ λͺ©λ‘μ
λλ€.
content:
application/json:
schema:
type: array
items:
type: object
properties:
id:
type: integer
description: μ¬μ©μ IDμ
λλ€.
name:
type: string
description: μ¬μ©μ μ΄λ¦μ
λλ€.
2. μ ν¨μ± κ²μ¬ λΌμ΄λΈλ¬λ¦¬ μ ννκΈ°
μ¬λ¬ μλ°μ€ν¬λ¦½νΈ λΌμ΄λΈλ¬λ¦¬κ° API μλ΅κ³Ό μμ²μ μ ν¨μ±μ κ²μ¬νλ λ° λμμ΄ λ μ μμ΅λλ€. λͺ κ°μ§ μΈκΈ° μλ μ΅μ μ λ€μκ³Ό κ°μ΅λλ€:
- Ajv (Another JSON Validator): λΉ λ₯΄κ³ νμ₯ κ°λ₯ν JSON μ€ν€λ§ μ ν¨μ± κ²μ¬κΈ°μ λλ€.
- Joi: μλ°μ€ν¬λ¦½νΈλ₯Ό μν κ°λ ₯ν μ€ν€λ§ μ€λͺ μΈμ΄ λ° λ°μ΄ν° μ ν¨μ± κ²μ¬κΈ°μ λλ€.
- tv4 (Tiny Validator v4): μκ³ λΉ λ₯Έ JSON μ€ν€λ§ μ ν¨μ± κ²μ¬κΈ°μ λλ€.
- Superstruct: μλ°μ€ν¬λ¦½νΈμμ λ°μ΄ν°λ₯Ό κ²μ¦νλ κ°λ¨νκ³ κ΅¬μ± κ°λ₯ν λ°©λ²μ λλ€.
κΈ°λ₯, μ±λ₯, μ¬μ© νΈμμ± μΈ‘λ©΄μμ νμμ λ§λ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ ννμΈμ.
3. μ ν¨μ± κ²μ¬ μ€ν€λ§ μ μνκΈ°
μ νν μ ν¨μ± κ²μ¬ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ¬ API μμ² λ° μλ΅μ μμ ꡬ쑰μ λ°μ΄ν° μ νμ μ€λͺ νλ μ€ν€λ§λ₯Ό μ μν©λλ€. μ΄ μ€ν€λ§λ APIμμ λ°νλ μ€μ λ°μ΄ν°μ μ ν¨μ±μ κ²μ¬νλ λ° μ¬μ©λ©λλ€.
μμ (Ajvμ JSON μ€ν€λ§):
const Ajv = require('ajv');
const ajv = new Ajv();
const schema = {
type: 'array',
items: {
type: 'object',
properties: {
id: { type: 'integer' },
name: { type: 'string' }
},
required: ['id', 'name']
}
};
const validate = ajv.compile(schema);
μμ (Joi):
const Joi = require('joi');
const schema = Joi.array().items(Joi.object({
id: Joi.number().integer().required(),
name: Joi.string().required()
}));
4. μ ν¨μ± κ²μ¬ ν μ€νΈ ꡬννκΈ°
APIμμ λ°μ΄ν°λ₯Ό κ°μ Έμ μ μλ μ€ν€λ§μ λν΄ μ ν¨μ±μ κ²μ¬νλ ν μ€νΈλ₯Ό μμ±ν©λλ€. Jest, Mocha λλ Jasmineκ³Ό κ°μ ν μ€νΈ νλ μμν¬λ₯Ό μ¬μ©νμ¬ μ΄λ¬ν ν μ€νΈλ₯Ό μ€νν μ μμ΅λλ€.
μμ (Jestμ Ajv):
const axios = require('axios');
const Ajv = require('ajv');
const ajv = new Ajv();
const schema = {
type: 'array',
items: {
type: 'object',
properties: {
id: { type: 'integer' },
name: { type: 'string' }
},
required: ['id', 'name']
}
};
const validate = ajv.compile(schema);
describe('GET /users', () => {
it('should return a list of users with valid data', async () => {
const response = await axios.get('/users');
expect(response.status).toBe(200);
const valid = validate(response.data);
expect(valid).toBe(true);
if (!valid) console.log(validate.errors);
});
});
5. μ ν¨μ± κ²μ¬ νλ‘μΈμ€ μλννκΈ°
μ ν¨μ± κ²μ¬ ν μ€νΈλ₯Ό μ§μμ ν΅ν©(CI) νμ΄νλΌμΈμ ν΅ν©νμΈμ. μ΄λ κ² νλ©΄ μ½λλ² μ΄μ€μ λ³κ²½ μ¬νμ΄ μμ λλ§λ€ APIκ° μλμΌλ‘ κ²μ¦λ©λλ€. Jenkins, GitLab CI, CircleCI, GitHub Actionsμ κ°μ λꡬλ₯Ό μ¬μ©νμ¬ μ΄ νλ‘μΈμ€λ₯Ό μλνν μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ νκ·κ° μ‘°κΈ°μ λ°κ²¬λκ³ μ ν리μΌμ΄μ μ΄ μΉ νλ«νΌ νμ€μ κ³μ μ€μνλλ‘ λ³΄μ₯ν©λλ€.
6. μ ν¨μ± κ²μ¬ μ€λ₯ μ²λ¦¬νκΈ°
μ ν¨μ± κ²μ¬ μ€λ₯κ° λ°μνλ©΄ κ°λ°μκ° λ¬Έμ λ₯Ό μ μνκ² μλ³νκ³ μμ νλ λ° λμμ΄ λλ λͺ ννκ³ μ μ΅ν μ€λ₯ λ©μμ§λ₯Ό μ 곡νλ κ²μ΄ μ€μν©λλ€. μ ν¨μ± κ²μ¬ λΌμ΄λΈλ¬λ¦¬λ μΌλ°μ μΌλ‘ μ€λ₯ λ©μμ§μ ν¬ν¨λ μ μλ μμΈν μ€λ₯ μ 보λ₯Ό μ 곡ν©λλ€.
μμ (Ajvλ₯Ό μ¬μ©ν μ€λ₯ μ²λ¦¬):
const axios = require('axios');
const Ajv = require('ajv');
const ajv = new Ajv();
const schema = {
type: 'array',
items: {
type: 'object',
properties: {
id: { type: 'integer' },
name: { type: 'string' }
},
required: ['id', 'name']
}
};
const validate = ajv.compile(schema);
describe('GET /users', () => {
it('should return a list of users with valid data', async () => {
const response = await axios.get('/users');
expect(response.status).toBe(200);
const valid = validate(response.data);
expect(valid).toBe(true);
if (!valid) {
console.log('Validation errors:');
validate.errors.forEach(error => {
console.log(` ${error.dataPath} ${error.message}`);
});
}
});
});
κ³ κΈ μ ν¨μ± κ²μ¬ κΈ°λ²
κΈ°λ³Έμ μΈ λ°μ΄ν° μ ν λ° κ΅¬μ‘° μ ν¨μ± κ²μ¬ μΈμλ λ€μκ³Ό κ°μ λ κ³ κΈ μ ν¨μ± κ²μ¬ κΈ°λ²μ ꡬνν μ μμ΅λλ€:
- μ¬μ©μ μ μ μ ν¨μ± κ²μ¬ κ·μΉ: νΉμ λΉμ¦λμ€ λ‘μ§μ΄λ μ μ½ μ‘°κ±΄μ μ μ©νκΈ° μν μ¬μ©μ μ μ μ ν¨μ± κ²μ¬ κ·μΉμ μ μν©λλ€.
- νλ κ° μ ν¨μ± κ²μ¬: μμ²μ΄λ μλ΅μ μλ‘ λ€λ₯Έ νλ κ°μ κ΄κ³λ₯Ό κ²μ¦ν©λλ€.
- λ¬Έλ§₯λ³ μ ν¨μ± κ²μ¬: API νΈμΆμ λ¬Έλ§₯(μ: μ¬μ©μ μν , μμ² λ§€κ°λ³μ)μ λ°λΌ λ€λ₯Έ μ ν¨μ± κ²μ¬ κ·μΉμ μ μ©ν©λλ€.
- μ±λ₯ ν μ€νΈ: λ€μν λΆν 쑰건μμ μλ΅ μκ°κ³Ό μ²λ¦¬λμ μΈ‘μ νμ¬ API μ±λ₯μ μ ν¨μ±μ κ²μ¬ν©λλ€. JMeterλ LoadViewμ κ°μ λκ΅¬κ° λμμ΄ λ μ μμ΅λλ€.
- 보μ ν μ€νΈ: SQL μΈμ μ , ν¬λ‘μ€ μ¬μ΄νΈ μ€ν¬λ¦½ν (XSS), μΈμ¦ μ°νμ κ°μ μΌλ°μ μΈ μ·¨μ½μ μ ν μ€νΈνμ¬ API 보μμ μ ν¨μ±μ κ²μ¬ν©λλ€. OWASP ZAPκ³Ό κ°μ λꡬλ₯Ό μ¬μ©ν μ μμ΅λλ€.
μμ: κ΅μ μ£Όμ νμ μ ν¨μ± κ²μ¬
μ£Όμ νμμ μ ν¨μ±μ κ²μ¬νλ κ²μ κ΅κ°λ§λ€ νμμ΄ λ€μνκΈ° λλ¬Έμ νΉν μ΄λ €μΈ μ μμ΅λλ€. κ²¬κ³ ν μ ν¨μ± κ²μ¬ νλ μμν¬λ μ΄λ¬ν λ€μμ±μ μ²λ¦¬ν μ μμ΄μΌ ν©λλ€.
λ―Έκ΅, μΊλλ€, μκ΅μ μ£Όμ μ ν¨μ±μ κ²μ¬ν΄μΌ νλ μμλ₯Ό μκ°ν΄ λ³΄κ² μ΅λλ€. κ° κ΅κ°λ κ³ μ ν μ£Όμ νμμ κ°μ§κ³ μμ΅λλ€:
- λ―Έκ΅: λλ‘λͺ μ£Όμ, λμ, μ£Ό, μ°νΈλ²νΈ(ZIP Code)
- μΊλλ€: λλ‘λͺ μ£Όμ, λμ, μ£Ό, μ°νΈλ²νΈ(Postal Code)
- μκ΅: λ²μ§μμ λλ‘λͺ , λμ, μ°νΈλ²νΈ(Postcode)
μ‘°κ±΄λΆ λ‘μ§μ΄ μλ JSON μ€ν€λ§λ₯Ό μ¬μ©νμ¬ μ¬λ¬ κ΅κ°μ μ£Όμ μ ν¨μ±μ κ²μ¬ν μ μμ΅λλ€:
{
"type": "object",
"properties": {
"country": {
"type": "string",
"enum": ["US", "CA", "UK"]
},
"address": {
"type": "object",
"oneOf": [
{
"properties": {
"streetAddress": { "type": "string" },
"city": { "type": "string" },
"state": { "type": "string", "enum": ["AL", "AK", "..."] },
"zipCode": { "type": "string", "pattern": "^[0-9]{5}(?:-[0-9]{4})?$" }
},
"required": ["streetAddress", "city", "state", "zipCode"],
"if": { "properties": { "country": { "const": "US" } } },
"then": { "description": "λ―Έκ΅ μ£Όμ" }
},
{
"properties": {
"streetAddress": { "type": "string" },
"city": { "type": "string" },
"province": { "type": "string", "enum": ["AB", "BC", "..."] },
"postalCode": { "type": "string", "pattern": "^[A-Za-z]\\d[A-Za-z][ -]?\\d[A-Za-z]\\d$" }
},
"required": ["streetAddress", "city", "province", "postalCode"],
"if": { "properties": { "country": { "const": "CA" } } },
"then": { "description": "μΊλλ€ μ£Όμ" }
},
{
"properties": {
"houseNumberAndStreetName": { "type": "string" },
"town": { "type": "string" },
"postcode": { "type": "string", "pattern": "^([A-Z][A-HJ-Y]?[0-9][A-Z0-9]? ?[0-9][A-Z]{2}|GIR ?0AA)$" }
},
"required": ["houseNumberAndStreetName", "town", "postcode"],
"if": { "properties": { "country": { "const": "UK" } } },
"then": { "description": "μκ΅ μ£Όμ" }
}
]
}
},
"required": ["country", "address"]
}
μ΄ μ€ν€λ§λ oneOf ν€μλλ₯Ό μ¬μ©νμ¬ country μμ±μ κ°μ λ°λΌ address μμ±μ΄ μΈ κ°μ§ μ£Όμ νμ μ€ νλλ₯Ό λ°λΌμΌ ν¨μ μ§μ ν©λλ€. μ κ· ννμ(pattern)μ ZIP μ½λμ μ°νΈλ²νΈ νμμ κ²μ¦νλ λ° μ¬μ©λ©λλ€.
μλ°μ€ν¬λ¦½νΈ API μ ν¨μ± κ²μ¬λ₯Ό μν λͺ¨λ² μ¬λ‘
- μ‘°κΈ° μμ: κ°λ° νλ‘μΈμ€ μ΄κΈ°λΆν° μ ν¨μ± κ²μ¬λ₯Ό ꡬννμΈμ.
- λ¨μνκ² μ μ§: κΈ°λ³Έμ μΈ μ ν¨μ± κ²μ¬ κ·μΉμΌλ‘ μμνμ¬ νμμ λ°λΌ μ μ§μ μΌλ‘ 볡μ‘μ±μ μΆκ°νμΈμ.
- μΌκ΄μ± μ μ§: λͺ¨λ APIμ κ±Έμ³ μΌκ΄λ μ ν¨μ± κ²μ¬ μ κ·Ό λ°©μμ μ¬μ©νμΈμ.
- μ€ν€λ§ λ¬Έμν: μ ν¨μ± κ²μ¬ μ€ν€λ§μ κ·Έ λͺ©μ μ λͺ ννκ² λ¬ΈμννμΈμ.
- μ² μ ν ν μ€νΈ: μ ν¨μ± κ²μ¬ κ·μΉμ΄ μ¬λ°λ₯΄κ² μλνλμ§ νμΈνκΈ° μν΄ ν¬κ΄μ μΈ ν μ€νΈλ₯Ό μμ±νμΈμ.
- μ±λ₯ λͺ¨λν°λ§: μ ν¨μ± κ²μ¬ νλ‘μΈμ€μ μ±λ₯μ λͺ¨λν°λ§νμ¬ μ 체 μ ν리μΌμ΄μ μ±λ₯μ μν₯μ λ―ΈμΉμ§ μλλ‘ νμΈμ.
- μ΅μ μν μ μ§: μ ν¨μ± κ²μ¬ λΌμ΄λΈλ¬λ¦¬μ μ€ν€λ§λ₯Ό μ΅μ μΉ νλ«νΌ νμ€μ λ§μΆ° μ λ°μ΄νΈνμΈμ.
- μ€μ μ§μ€μ κ΅¬μ± μ¬μ©: μΌκ΄μ±κ³Ό μ μ§λ³΄μ μ©μ΄μ±μ 보μ₯νκΈ° μν΄ μ ν¨μ± κ²μ¬ μ€ν€λ§λ₯Ό μ€μ μ§μ€μ μμΉ(μ: κ΅¬μ± νμΌ λλ λ°μ΄ν°λ² μ΄μ€)μ μ μ₯νμΈμ.
- λ¬Έλ§₯μ λ§λ μ€λ₯ λ©μμ§ μ 곡: κ°λ°μκ° λ¬Έμ λ₯Ό μ μνκ² μλ³νκ³ ν΄κ²°ν μ μλλ‘ μ€λ₯ λ©μμ§μ μΆ©λΆν λ¬Έλ§₯μ ν¬ν¨μν€μΈμ.
- API λ²μ κ΄λ¦¬ κ³ λ €: APIκ° μμ£Ό λ³κ²½λλ κ²½μ°, λ²μ κ΄λ¦¬λ₯Ό ꡬννκ³ κ° λ²μ μ λν΄ λ³λμ μ ν¨μ± κ²μ¬ μ€ν€λ§λ₯Ό μ μ§νμΈμ.
κ²°λ‘
μλ°μ€ν¬λ¦½νΈ API μ ν¨μ± κ²μ¬ νλ μμν¬λ μΉ νλ«νΌ νμ€ μ€μλ₯Ό 보μ₯νκ³ , μ½λ νμ§μ κ°μ νλ©°, κ²¬κ³ νκ³ μ μ§λ³΄μ κ°λ₯ν μΉ μ ν리μΌμ΄μ μ ꡬμΆνλ λ° νμμ μΈ λꡬμ λλ€. λͺ νν API λͺ μΈλ₯Ό μ μνκ³ , μ μ ν μ ν¨μ± κ²μ¬ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ ννλ©°, μλνλ ν μ€νΈλ₯Ό ꡬννκ³ , λͺ¨λ² μ¬λ‘λ₯Ό λ°λ₯΄λ©΄, λ€μν λΈλΌμ°μ μ κΈ°κΈ°μμ μμ μ μΌλ‘ μλνκ³ μ μΈκ³ μ¬μ©μμκ² μΌκ΄λ μ¬μ©μ κ²½νμ μ 곡νλ κ³ νμ§μ νμ€ μ€μ APIλ₯Ό μ 곡νλ λ° λμμ΄ λλ μ ν¨μ± κ²μ¬ νλ μμν¬λ₯Ό λ§λ€ μ μμ΅λλ€. μ μ€κ³λ μ ν¨μ± κ²μ¬ νλ μμν¬μ ν¬μνλ κ²μ μ±κ³΅μ μ΄κ³ μ§μ κ°λ₯ν μΉ μ ν리μΌμ΄μ μ ꡬμΆνλ λ° μ€μν λ¨κ³μ λλ€.
μ΄λ¬ν κΈ°μ κ³Ό μμΉμ μ±νν¨μΌλ‘μ¨ κ°λ°νμ κΈ°λ₯μ μ΄κ³ μ¬μ©μ μΉνμ μΌ λΏλ§ μλλΌ μ€λλ μ κΈλ‘λ²νλ λμ§νΈ νκ²½μμ νμ§, μνΈμ΄μ©μ± λ° μ μ§λ³΄μμ±μ μ΅κ³ νμ€μ μ€μνλ μΉ μ ν리μΌμ΄μ μ λ§λ€ μ μμ΅λλ€. μ΄λ¬ν λ Έλ ₯μ μμΉ, κΈ°κΈ° λλ λΈλΌμ°μ μ νΈλμ κ΄κ³μμ΄ λͺ¨λ μ¬μ©μμκ² μνν κ²½νμ 보μ₯ν©λλ€.